//
//  JQGeTuiService.m
//  JQGeTuiService
//
//  Created by JQZ on 2018/1/18.
//  Copyright © 2018年 JQ. All rights reserved.
//

#import "JQGeTuiService.h"

#ifdef DEBUG
#define DLog(fmt, ...) NSLog(fmt, ##__VA_ARGS__);
#else
#define DLog(...)
#endif

NSString *const JQNotificationsDeviceToken                    = @"NotificationsDeviceToken";
NSString *const JQNotificationsClientId                       = @"NotificationsGeTuiClientId";
NSString *const JQNotificationsGeTuiNotification              = @"NotificationsGeTuiNotification";
NSString *const JQNotificationsRemoteNotification             = @"NotificationsRemoteNotification";
NSString *const JQGeTuiServiceNotifyReceiveDeviceToken        = @"GeTuiServiceNotifyReceiveDeviceToken";
NSString *const JQGeTuiServiceNotifyReceiveGeTuiClientId      = @"GeTuiServiceNotifyReceiveGeTuiClientId";
NSString *const JQGeTuiServiceNotifyReceiveGeTuiNotification  = @"GeTuiServiceNotifyReceiveGeTuiNotification";
NSString *const JQGeTuiServiceNotifyReceiveRemoteNotification = @"GeTuiServiceNotifyReceiveRemoteNotification";

@implementation JQGeTuiService

JQ_EXPORT_SERVICE(JQGeTuiService)

#pragma mark - #UIApplicationDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    // 个推初始化
    DLog(@"JQGeTuiService初始化");
    [self initGeTui:launchOptions];
    
    return YES;
}

// 远程通知注册成功委托
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    
    NSString *newToken  = [deviceToken.description stringByReplacingOccurrencesOfString: @"<" withString: @""];
    newToken            = [newToken stringByReplacingOccurrencesOfString: @">" withString: @""];
    newToken            = [newToken stringByReplacingOccurrencesOfString: @" " withString: @""];
    
    DLog(@"Device token received in didRegisterForRemoteNotificationsWithDeviceToken: %@", newToken);
    [self notifyDidReceiveDeviceToken:newToken];
    [GeTuiSdk registerDeviceToken:newToken];
    
    // 持久化deviceToken
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    NSString *previousToken = [userDefaults objectForKey:JQNotificationsDeviceToken];
    if (![previousToken isEqualToString:newToken]) {
        DLog(@"Device Token has changed! OLD Value %@, NEW value %@", previousToken, newToken);
        [userDefaults setObject:newToken forKey:JQNotificationsDeviceToken];
        [userDefaults synchronize];
    }
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
    
    DLog(@"[DeviceToken失败]:%@", error.description);
    [GeTuiSdk registerDeviceToken:@""];
    
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults removeObjectForKey:JQNotificationsDeviceToken];
    [defaults removeObjectForKey:JQNotificationsClientId];
    [defaults synchronize];
}

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
    // 注册远程通知（推送）
    [application registerForRemoteNotifications];
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler {
    
    // 处理applicationIconBadgeNumber-1
    [self handlePushMessage:userInfo notification:nil];
    
    // 除了个推还要处理走苹果的信息放在body里面
    if (userInfo) {
        [self notifyDidReceiveRemoteMessage:userInfo];
    }
    
    // 处理APN
    DLog(@"[Receive RemoteNotification - Background Fetch]:%@", userInfo);
    completionHandler(UIBackgroundFetchResultNewData);
}

#pragma mark - #GeTuiSdkDelegate

/** SDK启动成功返回cid */
- (void)GeTuiSdkDidRegisterClient:(NSString *)clientId {
    // 个推SDK已注册，返回clientId
    DLog(@"[个推Cid] Getui clientId received in GeTuiSdkDidRegisterClient:%@", clientId);
    
    // 持久化client id
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    NSString *previousClientId = [userDefaults objectForKey:JQNotificationsClientId];
    if (![previousClientId isEqualToString:clientId]) {
        DLog(@"Getui clientId has changed! OLD Value %@, NEW value %@", previousClientId, clientId);
        [userDefaults setObject:clientId forKey:JQNotificationsClientId];
        [userDefaults synchronize];
    }
    
    [self notifyDidReceiveGeTuiClientId:clientId];
}

/** SDK遇到错误回调 */
- (void)GeTuiSdkDidOccurError:(NSError *)error {
    // [EXT]:个推错误报告，集成步骤发生的任何错误都在这里通知，如果集成后，无法正常收到消息，查看这里的通知。
    DLog(@"[GetuiSdk error]:%@", [error localizedDescription]);
    
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults removeObjectForKey:JQNotificationsClientId];
    [defaults synchronize];
}

/** SDK收到sendMessage消息回调 */
- (void)GeTuiSdkDidSendMessage:(NSString *)messageId result:(int)result {
    // [4-EXT]:发送上行消息结果反馈
    NSString *msg = [NSString stringWithFormat:@"sendmessage=%@,result=%d", messageId, result];
    DLog(@"[GetuiSdk DidSendMessage]:%@", msg);
}

/** SDK运行状态通知 */
- (void)GeTuiSDkDidNotifySdkState:(SdkStatus)aStatus {
    // [EXT]:通知SDK运行状态
    DLog(@"[GetuiSdk SdkState]:%u", aStatus);
}

/** SDK设置推送模式回调 */
- (void)GeTuiSdkDidSetPushMode:(BOOL)isModeOff error:(NSError *)error {
    if (error) {
        DLog(@"[GetuiSdk SetModeOff Error]:%@", [error localizedDescription]);
        return;
    }
    
    DLog(@"[GetuiSdk SetModeOff]:%@", isModeOff ? @"开启" : @"关闭");
}

/** 处理推送消息 */
- (void)handlePushMessage:(NSDictionary *)dict notification:(UILocalNotification *)localNotification {
    if ([UIApplication sharedApplication].applicationIconBadgeNumber != 0) {
        if (localNotification) {
            [[UIApplication sharedApplication] cancelLocalNotification:localNotification];
        }
        [UIApplication sharedApplication].applicationIconBadgeNumber -= 1;
    }
    else {
        [[UIApplication sharedApplication] cancelAllLocalNotifications];
        [UIApplication sharedApplication].applicationIconBadgeNumber = 0;
    }
}

/** SDK收到透传消息回调 */
- (void)GeTuiSdkDidReceivePayloadData:(NSData *)payloadData andTaskId:(NSString *)taskId andMsgId:(NSString *)msgId andOffLine:(BOOL)offLine fromGtAppId:(NSString *)appId {
    
    [self handlePushMessage:nil notification:nil];
    
    // 数据转换
    NSString *payloadMsg = nil;
    if (payloadData){
        payloadMsg = [[NSString alloc] initWithBytes:payloadData.bytes length:payloadData.length encoding:NSUTF8StringEncoding];
    }
    
    NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:
                          msgId?msgId:[NSNull null],@"aMsgId",
                          [NSNumber numberWithBool:offLine],@"offLine",
                          appId?appId:[NSNull null],@"appId",
                          payloadMsg?payloadMsg:[NSNull null],@"payload",
                          nil];
    [self notifyDidReceiveGeTuiMessage:dict];
}

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0

#pragma mark - #iOS10中收到推送消息

//  iOS 10: App在前台获取到通知
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler NS_AVAILABLE_IOS(10_0) {
    DLog(@"willPresentNotification：%@", notification.request.content.userInfo);
    // 根据APP需要，判断是否要提示用户Badge、Sound、Alert
    completionHandler(UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert);
}

//  iOS 10: 点击通知进入App时触发
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler NS_AVAILABLE_IOS(10_0) {
    DLog(@"didReceiveNotification：%@", response.notification.request.content.userInfo);
    NSDictionary *userInfo = [[NSDictionary alloc]init];
    userInfo = response.notification.request.content.userInfo;
    if (userInfo) {
        [self notifyDidReceiveRemoteMessage:userInfo];
    }
    
    // [ GTSdk ]：将收到的APNs信息传给个推统计
    [GeTuiSdk handleRemoteNotification:response.notification.request.content.userInfo];
    
    completionHandler();
}

#endif

#pragma mark - #自定义关于个推的内容
- (void)initGeTui:(NSDictionary *)launchOptions
{
    DLog(@"gtAppId = %@", self.gtAppId);
    DLog(@"gtAppKey = %@", self.gtAppKey);
    DLog(@"gtAppSecret = %@", self.gtAppSecret);
    
    // [ GTSdk ]：自定义渠道
    if (self.gtChannelId){
        [GeTuiSdk setChannelId:self.gtChannelId];
    }
    
    // 通过 appId、 appKey 、appSecret 启动SDK，注：该方法需要在主线程中调用
    [GeTuiSdk startSdkWithAppId:self.gtAppId appKey:self.gtAppKey appSecret:self.gtAppSecret delegate:self];
    
    // 注册APNS
    [self registerRemoteNotification];
    
    // 处理远程通知启动APP
    [self receiveNotificationByLaunchingOptions:launchOptions];
    
    // 个推SDK支持当APP进入后台后，个推是否运行。NO是不允许(为了让个APP进入后端时就直接走苹果推送)
    [GeTuiSdk runBackgroundEnable:NO];
}

#pragma mark - #用户通知(推送) _自定义方法

/** 注册用户通知 */
- (void)registerRemoteNotification {
    if ([[UIDevice currentDevice].systemVersion floatValue] >= 10.0) {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 // Xcode 8编译会调用
        if (@available(iOS 10.0, *)) {
            UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
            center.delegate = (id<UNUserNotificationCenterDelegate>)self;
            [center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionCarPlay) completionHandler:^(BOOL granted, NSError *_Nullable error) {
                if (!error) {
                    DLog(@"Request authorization succeeded!");
                }
            }];
        }
        [[UIApplication sharedApplication] registerForRemoteNotifications];
#else // Xcode 7编译会调用
        UIUserNotificationType types = (UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge);
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
        [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
        [[UIApplication sharedApplication] registerForRemoteNotifications];
#endif
    } else if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
        UIUserNotificationType types = (UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge);
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
        [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
        [[UIApplication sharedApplication] registerForRemoteNotifications];
    } else {
#if __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_8_0
        UIRemoteNotificationType apn_type = (UIRemoteNotificationType)(UIRemoteNotificationTypeAlert |
                                                                       UIRemoteNotificationTypeSound |
                                                                       UIRemoteNotificationTypeBadge);
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:apn_type];
#endif
    }
}

/** 自定义：APP被“推送”启动时处理推送消息处理（APP 未启动--》启动）*/
- (void)receiveNotificationByLaunchingOptions:(NSDictionary *)launchOptions {
    
    if (!launchOptions) return;
    
    /*
     通过“远程推送”启动APP
     UIApplicationLaunchOptionsRemoteNotificationKey 远程推送Key
     */
    NSDictionary *userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
    if (userInfo) {
        DLog(@"[Launching RemoteNotification]:%@", userInfo);
    }
}

#pragma mark - #通知回调
// 获得deviceToken
- (void)notifyDidReceiveDeviceToken:(NSString *)deviceToken {
    
    NSDictionary *userInfo = @{JQNotificationsDeviceToken:deviceToken?deviceToken:@""};
    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
    [notificationCenter postNotificationName:JQGeTuiServiceNotifyReceiveDeviceToken object:nil userInfo:userInfo];
    
    if ([self.delegate respondsToSelector:@selector(GeTuiServiceDidReceiveDeviceToken:)]){
        [self.delegate GeTuiServiceDidReceiveDeviceToken:deviceToken];
    }
}

// 获得个推id
- (void)notifyDidReceiveGeTuiClientId:(NSString *)clientId {
    
    NSDictionary *userInfo = @{JQNotificationsClientId:clientId?clientId:@""};
    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
    [notificationCenter postNotificationName:JQGeTuiServiceNotifyReceiveGeTuiClientId object:nil userInfo:userInfo];
    
    if ([self.delegate respondsToSelector:@selector(GeTuiServiceDidReceiveGeTuiClientId:)]){
        [self.delegate GeTuiServiceDidReceiveGeTuiClientId:clientId];
    }
}

// 处理个推本地通知，判断是否存在gtNotification方法
- (void)notifyDidReceiveGeTuiMessage:(NSDictionary *)message {
    
    NSDictionary *userInfo = @{JQNotificationsGeTuiNotification:message?message:@{}};
    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
    [notificationCenter postNotificationName:JQGeTuiServiceNotifyReceiveGeTuiNotification object:nil userInfo:userInfo];
    
    if ([self.delegate respondsToSelector:@selector(GeTuiServiceDidReceiveGeTuiNotification:)]){
        [self.delegate GeTuiServiceDidReceiveGeTuiNotification:message];
    }
}

// 处理苹果远程通知，判断是否存在receiveRemoteNotification方法
- (void)notifyDidReceiveRemoteMessage:(NSDictionary *)message {
    
    NSDictionary *userInfo = @{JQNotificationsGeTuiNotification:message?message:@{}};
    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
    [notificationCenter postNotificationName:JQGeTuiServiceNotifyReceiveRemoteNotification object:nil userInfo:userInfo];
    
    if ([self.delegate respondsToSelector:@selector(GeTuiServiceDidReceiveRemoteNotification:)]){
        [self.delegate GeTuiServiceDidReceiveRemoteNotification:message];
    }
}

@end
